package com.example.plantuml.tools;

import com.example.plantuml.model.MethodCall;
import com.example.plantuml.model.RequestTrace;
import net.sourceforge.plantuml.SourceStringReader;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * PlantUML时序图生成器
 */
@Service
public class PlantUmlGenerator {

    /**
     * 根据请求跟踪信息生成PlantUML时序图文本
     */
    public String generateSequenceDiagram(RequestTrace trace) {
        if (trace == null || trace.getRootMethod() == null) {
            return "";
        }

        StringBuilder sb = new StringBuilder();

        // 开始PlantUML定义
        sb.append("@startuml\n");
        sb.append("title " + "时序图 - ").append(trace.getHttpMethod())
                .append(" ").append(trace.getRequestUrl()).append(" (总耗时: ")
                .append(trace.getTotalDuration()).append("ms, Trace ID: ").append(trace.getTraceId()).append(")\n\n");

        // 收集所有参与者(类)
        Set<String> participants = new LinkedHashSet<>();
        participants.add("Client"); // 添加客户端作为参与者
        participants.addAll(collectParticipants(trace.getRootMethod()));

        // 声明参与者
        for (String participant : participants) {
            sb.append("participant ").append(participant).append("\n");
        }

        sb.append("\n");

        // 客户端发起请求
        sb.append("Client -> ").append(trace.getRootMethod().getClassName())
                .append(": ").append(trace.getHttpMethod()).append(" ").append(trace.getRequestUrl()).append("\n");

        sb.append("activate ").append(trace.getRootMethod().getClassName()).append("\n\n");

        // 生成方法调用序列
        generateMethodCalls(trace.getRootMethod(), sb, 0);

        // 客户端接收响应
        sb.append("\n").append(trace.getRootMethod().getClassName()).append(" --> Client: 响应结果\n");
        sb.append("deactivate ").append(trace.getRootMethod().getClassName()).append("\n");

        // 结束PlantUML定义
        sb.append("@enduml\n");

        return sb.toString();
    }

    /**
     * 收集所有参与的类
     */
    private Set<String> collectParticipants(MethodCall methodCall) {
        Set<String> participants = new LinkedHashSet<>();
        if (methodCall == null) {
            return participants;
        }

        participants.add(methodCall.getClassName());

        for (MethodCall child : methodCall.getChildren()) {
            participants.addAll(collectParticipants(child));
        }

        return participants;
    }

    /**
     * 递归生成方法调用序列
     */
    private void generateMethodCalls(MethodCall methodCall, StringBuilder sb, int depth) {
        if (methodCall == null || methodCall.getChildren().isEmpty()) {
            return;
        }

        String indent = getIndent(depth);

        for (MethodCall child : methodCall.getChildren()) {
            // 方法调用
            sb.append(indent).append(methodCall.getClassName()).append(" -> ")
                    .append(child.getClassName()).append(": ")
//                    .append(child.getComponentName()).append("\\n")
                    .append(child.getMethodName()).append(child.getParameterDesc()).append(" (").append(child.getDuration()).append("ms)")
                    .append("\n");

            // 如果有子调用，激活目标类
            if (!child.getChildren().isEmpty()) {
                sb.append(indent).append("activate ").append(child.getClassName()).append("\n");
            }

            // 递归处理子调用
            generateMethodCalls(child, sb, depth + 1);

            // 如果有子调用，解除激活
            if (!child.getChildren().isEmpty()) {
                sb.append(indent).append("deactivate ").append(child.getClassName()).append("\n");
            }

            // 返回结果
            sb.append(indent).append(child.getClassName()).append(" --> ")
                    .append(methodCall.getClassName()).append(": 返回结果\n");
        }
    }

    /**
     * 生成缩进
     */
    private String getIndent(int depth) {
        StringBuilder indent = new StringBuilder();
        for (int i = 0; i < depth; i++) {
            indent.append("  ");
        }
        return indent.toString();
    }

    /**
     * 将PlantUML文本转换为PNG图片字节数组
     */
    public byte[] generatePngImage(String plantUmlText) throws IOException {
        SourceStringReader reader = new SourceStringReader(plantUmlText);
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            // 生成PNG格式图片
            reader.outputImage(outputStream);
            return outputStream.toByteArray();
        }
    }
}
